// import com.alibaba.druid.sql.ast.SQLDeclareItem;
// import com.alibaba.druid.sql.ast.SQLObject;
// import com.alibaba.druid.sql.ast.SQLOver;
// import com.alibaba.druid.sql.ast.SQLParameter;
// import com.alibaba.druid.sql.ast.expr.*;
// import com.alibaba.druid.sql.ast.statement.*;
// import com.alibaba.druid.sql.visitor.SQLASTVisitor;

// import java.util.HashMap;
// import java.util.std::map;

// import static com.alibaba.druid.sql.repository.SchemaResolveVisitorFactory.*;
#pragma once
#include "../visitor/SQLASTVisitor.h"
#include <map>

class SchemaResolveVisitor_Option
{
public:
  static SchemaResolveVisitor_Option_ptr ResolveAllColumn;
  static SchemaResolveVisitor_Option_ptr ResolveIdentifierAlias;
  static SchemaResolveVisitor_Option_ptr CheckColumnAmbiguous;

  SchemaResolveVisitor_Option(uint64_t mask, string_ptr name);

  int mask_;
  std::string name_;

  static int of(SchemaResolveVisitor_Option_list_ptr options);
};

class SchemaResolveVisitor_Context
{
public:
  SchemaResolveVisitor_Context_ptr parent;
  SQLObject_ptr object;
  int level;

  SQLTableSource_ptr tableSource;

  SQLTableSource_ptr from;

  std::map<long, SQLTableSource_ptr> tableSourceMap;

  std::map<long, SQLDeclareItem_ptr> declares;

  SchemaResolveVisitor_Context(SQLObject_ptr object, SchemaResolveVisitor_Context_ptr parent);

  SQLTableSource_ptr getFrom();

  void setFrom(SQLTableSource_ptr from);

  SQLTableSource_ptr getTableSource();

  void setTableSource(SQLTableSource_ptr tableSource);

  void addTableSource(long alias_hash, SQLTableSource_ptr tableSource);

  void declare(SQLDeclareItem_ptr x);

  SQLDeclareItem_ptr findDeclare(long nameHash);

  SQLTableSource_ptr findTableSource(long nameHash);

  SQLTableSource_ptr findTableSourceRecursive(long nameHash);
};

class SchemaResolveVisitor : virtual public SQLASTVisitor
{
public:
SHAREDOBJECT(SchemaResolveVisitor)     ;
  BOOL_ptr isEnabled(SchemaResolveVisitor_Option_ptr option);

  int getOptions();

  SchemaRepository_ptr getRepository();

  SchemaResolveVisitor_Context_ptr getContext();

  SchemaResolveVisitor_Context_ptr createContext(SQLObject_ptr object);

  void popContext();

  bool visit(SQLSelectStatement_ptr x);

  bool visit(SQLSelect_ptr x);

  bool visit(SQLWithSubqueryClause_ptr x);

  // BOOL_ptr visit(SQLIfStatement_ptr x);

  // BOOL_ptr visit(SQLCreateFunctionStatement_ptr x);

  bool visit(SQLExprTableSource_ptr x);

  bool visit(SQLSelectQueryBlock_ptr x);

  bool visit(SQLForeignKeyImpl_ptr x);

  bool visit(SQLIdentifierExpr_ptr x);

  bool visit(SQLPropertyExpr_ptr x);

  bool visit(SQLBinaryOpExpr_ptr x);

  bool visit(SQLAllColumnExpr_ptr x);

  bool visit(SQLCreateTableStatement_ptr x);

  bool visit(SQLUpdateStatement_ptr x);

  bool visit(SQLDeleteStatement_ptr x);

  // BOOL_ptr visit(SQLAlterTableStatement_ptr x);

  bool visit(SQLInsertStatement_ptr x);

  bool visit(SQLParameter_ptr x);

  bool visit(SQLDeclareItem_ptr x);

  bool visit(SQLOver_ptr x);

  bool visit(SQLMethodInvokeExpr_ptr x);

  bool visit(SQLUnionQuery_ptr x);

  // BOOL_ptr visit(SQLMergeStatement_ptr x);

  // BOOL_ptr visit(SQLCreateProcedureStatement_ptr x);

  bool visit(SQLBlockStatement_ptr x);

  // BOOL_ptr visit(SQLReplaceStatement_ptr x);

  bool visit(SQLCastExpr_ptr x);

  // BOOL_ptr visit(SQLFetchStatement_ptr x);
};
